/*!
   \file

   © 2011 Mark W. Gabby II

   This file is part of the Avion engine.

   The Avion engine is free software: you can redistribute it and/or modify it under the terms of
   the GNU General Public License as published by the Free Software Foundation, either version 3 of
   the License, or (at your option) any later version.

   The Avion engine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
   without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
   the GNU General Public License for more details.

   You should have received a copy of the GNU General Public License along with the Avion Engine.
   If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <list>
#include <map>

#include "Components/icBase.hpp"

#include "Systems/Constants/InputTypes.hpp"

struct icControllerMessage
{
   struct
   {
      eControllerButton button;
      eKeyState state;
   } raw;

   uint32_t mapping;
};

/*!
    A controller component. Controllers can be queried for axis positions and set up to send button
    messages when buttons are pressed or released.
*/
class icController : public icBase
{
public:
   icController( Entity * Owner );
   void SetSendRawMessages( bool SendRawMessages );

   bool AddMapping( const eControllerButton Button, const eKeyState State, const uint32_t Value,
                    const bool Overwrite = false );

   void AddAxisMapping( const eControllerAxis Which, const float Min, const float Max );

   bool GetAxis( float & AxisValue, const eControllerAxis Which );

   bool GetNextMessage( icControllerMessage & Output );


   void ClearMessagesList();


   bool ButtonDown( const eControllerButton Which );

private:
   friend class Input;

   void UpdateAxis( ControllerAxisMessage Message );

   void SendButton( ControllerButtonMessage Message );

   void SetAxisAvailable( const eControllerAxis Which, const bool Available );
private:
   uint32_t RegisterConcreteClassWithSystem();

   float normalizedAxisPositions[kMaxControllerAxes];
   float mappedAxisMins[kMaxControllerAxes];
   float mappedAxisMaxes[kMaxControllerAxes];

   bool axisAvailable[kMaxControllerAxes];

   bool buttonDown[kMaxControllerButtons];

   bool rawMessagesOn;
   std::map<ControllerButtonMessage, uint32_t> buttonActionsToValues;
   std::list<icControllerMessage> messages;
};
